package com.hsq.ndmall.common.config;

import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.time.Duration;

/**
 * @author 黄四清
 * @version 1.0.0
 * @ClassName RedisConfig.java
 * @Description TODO redis核心配置
 * @createTime 2021年08月17日 14:54:00
 */
@Configuration
public class RedisConfig {
    // 不配置也是可以的，如果不配，springboot会通过RedisAutoConfiguration类，自动会我们帮我们注入redisTemplate
    //  之所有配置，因为它采用的key与value默认采用的是JDK的序列化
    //  1）JDK的序列化的缺点： （1）占用资源大，存储数量比较大.（2）阅读性比较差
    //  2) 自定义我们自己的序列化的一个方式，key采用StringRedisSerializer序列化，value采用GenericJackson2JsonRedisSerializer（spring默认的）
    @Bean(name = "redisTemplate")
    @Primary
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){

        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();

        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(keySerializer());
        redisTemplate.setHashKeySerializer(keySerializer());
        redisTemplate.setValueSerializer(valueSerializer());
        redisTemplate.setHashValueSerializer(valueSerializer());
        return redisTemplate;
    }

    /**
     *
     * @param redisConnectionFactory
     * @return
     */
    @Primary  //自动装配时当出现多个Bean候选者时，被注解为@Primary的Bean将作为首选者，否则将抛出异常。（只对接口的多个实现生效）
    @Bean
    public  CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
        //缓存配置对象
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration
                .entryTtl(Duration.ofMinutes(30L))      //设置缓存的默认超时时间：30分钟
                .disableCachingNullValues()             //如果是空值，不缓存
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))         //设置key序列化器
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer((valueSerializer())));  //设置value序列化器

        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration).build();
    }

    /**
     * key 采用
     * @return
     */
    private RedisSerializer<String> keySerializer() {

        return new StringRedisSerializer();
    }

    /**
     * value 采用Jackson
     * @return
     */
    private RedisSerializer<Object> valueSerializer() {

        return new GenericJackson2JsonRedisSerializer();
    }


}
